# -*- coding: utf-8 -*-
"""
Created on Thu Oct 18 15:39:50 2018
使用时copy进相应的代码中
@author: HP
"""
import time
import pandas as pd
import numpy as np
import re
from sklearn.model_selection import cross_val_score


class AdjustParam(object):
    '''
    model：最优模型
    ort_res: 正交试验结果
    param_res：各因素水平结果
    '''
    def __init__(self, X, y, scoring=None, cv=5):
        self.X = X
        self.y = y
        self.scoring = scoring
        self.cv = cv
        self.model = None
        self.ort_res = None
        self.param_res = None
    
    def run_ort(self, model, df_params):
        model_str = str(model)
        k=0
        n=len(df_params.index)
        df_params['ort_res'] = 0
        df_params['ort_res_std'] = 0
        df_params['ort_train_time'] = 0
        for i in df_params.index:
            k+=1
            params_li = list(map(lambda x:x+'='+ str(df_params.loc[i, x]),df_params.columns[:-3]))
            param_str = ', '.join(params_li)
            print(param_str)
            for re_p in params_li:
                p_val = re_p.split('=')[0]
                model_str = re.sub('%s=[^,)]*'%p_val, re_p ,model_str)
            model_ = eval(model_str)
            t1=time.time()
            cv_score = cross_val_score(model_, self.X, self.y, cv = 5, n_jobs = -1, scoring='neg_mean_squared_error' )
            err = np.sqrt(-cv_score)
            res = np.mean(err)
            res_std = np.std(cv_score)
            t2 = int(time.time()-t1)
            print('res: %f, time: %d, num: %d/%d'%(res,t2,k,n))
            df_params.loc[i,'ort_res'] = res
            df_params.loc[i,'ort_res_std'] = res_std
            df_params.loc[i,'ort_train_time'] = t2
        self.ort_res = df_params
        # 筛选最优值
        res_li = list(map(lambda x: df_params.groupby(x).ort_res.mean().argmin(), df_params.columns[:-3]))
        param_li = df_params.columns[:-3]
        param_opt = list(map(lambda x: '='.join(x), zip(param_li,map(str,res_li))))
        # 最优RF模型
        for re_p in param_opt:
            p_val = re_p.split('=')[0]
            model_str = re.sub('%s=[^,)]*'%p_val, re_p ,model_str)
        self.model = eval(model_str)

        temp_li = []
        for i in df_params.columns[:-3]:
            temp = df_params.groupby(i).mean()[['ort_res','ort_res_std','ort_train_time']].sort_values(['ort_res','ort_res_std','ort_train_time'])
            temp = temp.rename(index = lambda x: str(i) + '=' + str(x))
            temp_li.append(temp)
        self.param_res = pd.concat(temp_li)
